<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"
    />
    <!-- 在 body 结束标签前引入 highlight.js 脚本 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
    <!-- and it's easy to individually load additional languages -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <title>SSE</title>
    <style>
      div {
        width: 100%;
      }
      body {
        padding: 40px;
      }
      #err {
        margin-top: 100px;
        color: red;
      }
      #inputsend {
        display: flex;
        align-items: center;
      }
      #send {
        margin-left: 20px;
      }
    </style>
  </head>
  <body>
    <div id="inputsend">
      <textarea id="input"></textarea>
      <button id="send">发送</button>
    </div>
    <div id="aaa"></div>
    <div id="err"></div>
    <script>
      async function fetchSSE({ url, data, headers = [], onMessage, onError }) {
        let reader, decoder;
        if (!url) {
          alert("url 不能为空");
          return;
        }
        const response = await fetch(url, {
          method: "POST",
          body: data ? JSON.stringify(data) : null,
          headers: {
            ...headers,
          },
        });

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        reader = response.body.getReader();
        decoder = new TextDecoder();

        const readLoop = async () => {
          while (true) {
            const { done, value } = await reader.read();
            if (done) {
              break;
            }
            const chunk = decoder.decode(value);
            const lines = chunk.split("\n");
            for (const line of lines) {
              if (line.trim()) {
                try {
                  const data = JSON.parse(line.substring(5, line.length));
                  onMessage(data);
                } catch (err) {
                  onError(err);
                }
              }
            }
          }
        };

        readLoop().catch(onError);

        // 返回一个函数，用于关闭SSE连接
        return () => {
          reader.cancel();
        };
      }

      const aaaDOM = document.getElementById("aaa");
      const errDOM = document.getElementById("err");
      function onMessage(data) {
        if (data?.output?.text) {
          aaaDOM.innerHTML = marked.parse(data.output.text);
          hljs.highlightAll();
        }
      }

      function onError(err) {
        // console.log(err);
        // errDOM.appendChild(document.createTextNode(err.message));
      }

      function send(e) {
        const cancel = fetchSSE({
          url: "/sse?_csrf={{{ctx.csrf}}}",
          data: {
            model: "qwen-max",
            input: {
              messages: [
                {
                  role: "system",
                  content: "You are a helpful assistant.",
                },
                {
                  role: "user",
                  content: document.getElementById("input").value,
                },
              ],
            },
            parameters: {},
          },
          headers: {
            Accept: "text/event-stream",
            "Content-Type": "application/json",
            "x-response-stream": "true",
            "X-DashScope-SSE": "enable",
            //   Authorization: `Bearer ${apiKey}`,
          },
          onMessage,
          onError,
        });
      }
      document.getElementById("send").addEventListener("click", send);

      //   const apiKey = "sk-c4075048444b4782a1359f51f1c28b99";
    </script>
    <script>
        
      </script>
  </body>
</html>
